import { nextTick, onBeforeMount, ref, Ref, unref } from "vue";
import { EmitType, ElRef } from "/#/index";
import { Routers as Menu } from "@/router";
import { useI18n } from "@/hooks/web/useI18n";
import { useGo } from "@/hooks/web/usePage";
import { onKeyStroke, useDebounceFn } from '@vueuse/core';
import { filter, forEach } from "@/utils/helper/treeHelper";
import { useScrollTo } from "@/hooks/event/useScrollTo";
import { getMenus } from "@/router/menu";
import { cloneDeep } from "lodash-es";


export interface SearchResult {
  name: string;
  path: string;
  icon?: string;
}

// Translate special characters
function transform(c: string) {
  const code: string[] = ['$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'];
  return code.includes(c) ? `\\${c}` : c;
}

function createSearchReg(key: string) {
  const keys = [...key].map((item) => transform(item));
  const str = ['', ...keys, ''].join('.*');
  return new RegExp(str);
}

export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>, emit: EmitType) {
  const searchResult = ref<SearchResult[]>([]);
  const keyword = ref('');
  const activeIndex = ref(-1);


  let menuList: Menu[] = [];
  // const { t } = useI18n();
  const go = useGo();
  //useDebounceFn 延迟执行
  // 查询方法
  const handleSearch = useDebounceFn(search, 200);


  onBeforeMount(async () => {
    const list = await getMenus();
    menuList = cloneDeep(list);
    // forEach(menuList, (item) => {
    //   item.name = t(item.name);
    // });
  });

  function search(value: string) {
    keyword.value = value.trim();
    if (!value) {
      // 如果没有值，清空查询
      searchResult.value = [];
      return;
    }
    const reg = createSearchReg(unref(keyword))
    const filterMenu = filter(menuList, (item) => {
      console.log(item.meta.title)
      return reg.test(item.meta.title) && !item.meta.hidden;
    });
    searchResult.value = handlerSearchResult(filterMenu, reg);
    console.log(searchResult.value)

    activeIndex.value = 0;
  }

  // 组织查询结果
  function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) {
    const ret: SearchResult[] = [];
    filterMenu.forEach((item) => {
      const { meta, path, children, hidden } = item;
      console.log(item)
      if (!hidden && reg.test(meta.title) && (!children?.length)) {
        ret.push({
          name: parent?.meta.title ? `${parent.meta.title} > ${meta.title}` : meta.title,
          path,
          icon: meta.icon
        })
      }

      if (Array.isArray(children) && children.length) {
        ret.push(...handlerSearchResult(children, reg, item));
      }
    })
    return ret
  }

  // Activate when the mouse moves to a certain line
  function handleMouseenter(e: any) {
    const index = e.target.dataset.index;
    activeIndex.value = Number(index);
  }

  // Arrow key up
  function handleUp() {
    if (!searchResult.value.length) return;
    activeIndex.value--;
    if (activeIndex.value < 0) {
      activeIndex.value = searchResult.value.length - 1;
    }
    handleScroll();
  }

  // Arrow key down
  function handleDown() {
    if (!searchResult.value.length) return;
    activeIndex.value++;
    if (activeIndex.value > searchResult.value.length - 1) {
      activeIndex.value = 0;
    }
    handleScroll();
  }

  // When the keyboard up and down keys move to an invisible place
  // the scroll bar needs to scroll automatically
  function handleScroll() {
    const refList = unref(refs);
    if (!refList || !Array.isArray(refList) || refList.length === 0 || !unref(scrollWrap)) {
      return;
    }

    const index = unref(activeIndex);
    const currentRef = refList[index];
    if (!currentRef) {
      return;
    }
    const wrapEl = unref(scrollWrap);
    if (!wrapEl) {
      return;
    }
    const scrollHeight = currentRef.offsetTop + currentRef.offsetHeight;
    const wrapHeight = wrapEl.offsetHeight;
    const { start } = useScrollTo({
      el: wrapEl,
      duration: 100,
      to: scrollHeight - wrapHeight,
    });
    start();
  }

  // enter keyboard event
  async function handleEnter() {
    if (!searchResult.value.length) {
      return;
    }
    const result = unref(searchResult);
    const index = unref(activeIndex);
    if (result.length === 0 || index < 0) {
      return;
    }
    const to = result[index];
    handleClose();
    await nextTick();
    go(to.path);
  }

  // close search modal
  function handleClose() {
    searchResult.value = [];
    emit('close');
  }

  // enter search
  onKeyStroke('Enter', handleEnter);
  // Monitor keyboard arrow keys
  onKeyStroke('ArrowUp', handleUp);
  onKeyStroke('ArrowDown', handleDown);
  // esc close
  onKeyStroke('Escape', handleClose);

  return { handleSearch, searchResult, keyword, activeIndex, handleMouseenter, handleEnter };

}
